From: Andrew Cooper Date: Mon, 27 Mar 2017 09:28:53 +0000 (+0000) Subject: x86/emul: Correct the decoding of vlddqu X-Git-Tag: archive/raspbian/4.11.1-1+rpi1~1^2~66^2~2391 X-Git-Url: https://dgit.raspbian.org/%22http://www.example.com/cgi/%22/%22http:/www.example.com/cgi/%22?a=commitdiff_plain;h=62cd2f6c887e1108be6c7950451527b3d1056da6;p=xen.git x86/emul: Correct the decoding of vlddqu vlddqu is encoded with 0xf2 which causes it to fall into the Scalar general case in x86_decode_twobyte(). However, it really does have just two operands, so must remain TwoOp AFL discovered that the instruction c5 5b f0 3c e5 95 0a cd 63 was considered valid despite it being a two operand instruction and VEX.vvvv having the value 11. The resulting use in a stub yielded #UD. Signed-off-by: Andrew Cooper Acked-by: Jan Beulich --- diff --git a/xen/arch/x86/x86_emulate/x86_emulate.c b/xen/arch/x86/x86_emulate/x86_emulate.c index bb67be65bc..497cc77c65 100644 --- a/xen/arch/x86/x86_emulate/x86_emulate.c +++ b/xen/arch/x86/x86_emulate/x86_emulate.c @@ -2310,7 +2310,8 @@ x86_decode_twobyte( case 0x7f: case 0xc2 ... 0xc3: case 0xc5 ... 0xc6: - case 0xd0 ... 0xfe: + case 0xd0 ... 0xef: + case 0xf1 ... 0xfe: ctxt->opcode |= MASK_INSR(vex.pfx, X86EMUL_OPC_PFX_MASK); break; @@ -2332,9 +2333,9 @@ x86_decode_twobyte( if ( vex.pfx == vex_f3 ) /* movq xmm/m64,xmm */ { case X86EMUL_OPC_VEX_F3(0, 0x7e): /* vmovq xmm/m64,xmm */ - state->desc = DstImplicit | SrcMem | Mov; + state->desc = DstImplicit | SrcMem | TwoOp; state->simd_size = simd_other; - /* Avoid the state->desc adjustment below. */ + /* Avoid the state->desc clobbering of TwoOp below. */ return X86EMUL_OKAY; } break; @@ -2374,11 +2375,25 @@ x86_decode_twobyte( case X86EMUL_OPC_VEX_66(0, 0xc4): /* vpinsrw */ state->desc = DstReg | SrcMem16; break; + + case 0xf0: + ctxt->opcode |= MASK_INSR(vex.pfx, X86EMUL_OPC_PFX_MASK); + if ( vex.pfx == vex_f2 ) /* lddqu mem,xmm */ + { + /* fall through */ + case X86EMUL_OPC_VEX_F2(0, 0xf0): /* vlddqu mem,{x,y}mm */ + state->desc = DstImplicit | SrcMem | TwoOp; + state->simd_size = simd_other; + /* Avoid the state->desc clobbering of TwoOp below. */ + return X86EMUL_OKAY; + } + break; } /* * Scalar forms of most VEX-encoded TwoOp instructions have - * three operands. + * three operands. Those which do really have two operands + * should have exited earlier. */ if ( state->simd_size && vex.opcx && (vex.pfx & VEX_PREFIX_SCALAR_MASK) )